//
//  HOPNetworkTools.swift
//  WB01
//
//  Created by HOP on 15/12/18.
//  Copyright © 2015年 HOP. All rights reserved.
//

import UIKit

import AFNetworking
// 使用枚举来统一管理错误
enum HOPNetworkError: Int {
  case emptyAccessToken = -1 // AccessToken没有值
  case emptyUid = -2 // Uid没有值
    // 枚举除了有成员之外,还可以有属性和方法
    // 将错误的code和错误的描述关联起来, 使用计算性属性,只有get(只读计算性属性)
    var errorDescription: String {
        get {
        // 判断不同的类型返回不同的错误信息
            switch self {
            case HOPNetworkError.emptyAccessToken:
                return "access_token没有值"
            case HOPNetworkError.emptyUid:
                return "uid没有值"
            }
        
        }
    
    }
    // 定义一个方法,返回一个错误,根据枚举类型不一样返回不一样的错误
    func error() -> NSError {
        return NSError(domain: "network", code: self.rawValue, userInfo: ["errorDescription" : self.errorDescription])
    
    }
    
    

}
class HOPNetworkTools: AFHTTPSessionManager {
//    // 网络单例继承AFN
//    // 单例, 调用默认构造方法
//        static let sharedInsatance: HOPNetworkTools = {
//        // baseURL,api前面的内容是一样的
//        let baseURL = NSURL(string: "https://api.weibo.com/")
//            let tools = HOPNetworkTools(baseURL: baseURL)
//            return tools
//           // 设置响应的序列化器,支持text/plain
//            
//    }()
    // 单例, 调用默认构造方法
    static let sharedInstance: HOPNetworkTools = HOPNetworkTools()
    
    // 不让别人访问构造方法
    private init () {
        // 没有初始化的属性
        let baseURL = NSURL(string: "https://api.weibo.com/")!
        // 在构造函数里面子类不能调用父类的便利构造函数,需要调用父类的指定构造函数
        //        super.init(baseURL: baseURL)
        super.init(baseURL: baseURL, sessionConfiguration: nil)
        // 方法的调用必须在 super.init 只有 调用父类的super.init之后,对象才创建完毕,对象创建完毕才能调用对象的方法
        
        // 设置响应的序列化器,支持text/plain
        self.responseSerializer.acceptableContentTypes?.insert("text/plain")
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    
    
    
    // MARK: - 授权相关
    private let client_id = "3793344063"
     let redirect_uri = "http://www.baidu.com/"
    private let client_secret = "7bc60ddd52c324b105f860536d81fe6d"
    /// 拼接登陆界面的URL地址
    func oAuthURL() -> NSURL {
    let urlString = "https://api.weibo.com/oauth2/authorize?client_id=\(client_id)&redirect_uri=\(redirect_uri)"
       return NSURL(string: urlString)!
      }
    
    
    
    
    // MARK: - 加载AccessToken
     // 当网络请求成功会失败需要告诉调用的对象,使用闭包回调
    func loadAccessToken(code: String, finished: (result: [String: AnyObject]?, error:NSError?) -> ()) {
        // url地址
    let urlString = "https://api.weibo.com/oauth2/access_token"
    // 请求参数,字典
        let parameters = [
            "client_id": client_id,
            "client_secret": client_secret,
            "grant_type": "authorization_code",
            "code": code,
            "redirect_uri": redirect_uri
                ]
    
    // 发送POST请求
        POST(urlString, parameters: parameters, success: { (_, result) -> Void in
            // 调用闭包,
            // 需要将返回结果转成字典, 使用 as?,因为闭包的result参数是一个
            let dict = result as? [String: AnyObject]
            finished(result: dict ,error : nil)
            }) { (_, error) -> Void in
                finished(result: nil ,error : error)
        }
    
    
    }
    
    /// MAR: - 加载用户信息
    func loadUserInfo(finished: (result: [String: AnyObject]?, error: NSError?) -> ()){
      // 1.获取AccessToken,判断AccessToken是否有值
    // 守卫
    guard let access_token = HOPuserAccount.loadUserAccount()?.access_token else {
    // 没有值就进来
    print("access_token没有值")
    return
      }
    // 能到这里来说明 access_token 是有值的
    // 2.获取用户的uid
    guard let uid = HOPuserAccount.loadUserAccount()?.uid else {
    // 能到这里面来uid没有值
    print("uid没有值")
    return
     }
    // 能到这里来说明uid是有值的.
    
    // 3.url地址, 可以省略baseURL,AFN会自动帮我们加上
    let urlString = "2/users/show.json"
     // 4.请求参数
    let parameters = [
    "access_token": access_token,
    "uid": uid
    
    ]
    // 5.发送请求获取用户数据

    GET(urlString, parameters: parameters, success: { (_, result) -> Void in
        // 6.调用准备好的闭包
        let dict = result as? [String: AnyObject]
        finished(result: dict, error: nil)
        }) { (_, error) -> Void in
            // 6.调用准备好的闭包
            finished(result: nil, error: error)
        }
      }
    
    // MARK: - 获取微博数据
    func loadStatus(since_id: Int, max_id: Int,finished: (result: [String: AnyObject]?, error: NSError?) -> ()) {
    // 5.1. 判断access_token
        guard let access_token = HOPuserAccount.loadUserAccount()?.access_token else {
            let error = HOPNetworkError.emptyAccessToken.error()
            finished(result: nil, error: error)
            return
            }
    // 5.2. url地址
        let urlString = "2/statuses/home_timeline.json"
     // 5.3. 请求参数
        var parameters: [String: AnyObject] = ["access_token": access_token]
        if since_id > 0 {
        // 表示别人传了since_id, 下拉刷新微博数据
        parameters["since_id"] = since_id
        }else if max_id > 0 {
            // 表示别人传了max_id, 上拉加载更多微博数据
            // 若指定此参数，则返回ID小于或等于max_id的微博,不需要等于的微博
         parameters["max_id"] = max_id - 1
        
        }
        let debug = false 
        if debug {
        loadLocalStatus(finished)
        
        }else {
        
    // 5.4. 发送请求
        GET(urlString, parameters: parameters, success: { (_, result) -> Void in
            // 5.5.闭包回调,获得到数据
            let dict = result as? [String: AnyObject]
            finished(result: dict, error: nil)
            }) { (_, error) -> Void in
                // 5.5.闭包回调,出现了错误
                finished(result: nil, error: error)
        }
 
    }
    }
    // MARK: - 加载本地数据
    func loadLocalStatus(finished: (result: [String: AnyObject]?,error: NSError?) -> ()) {
    // 1.获取statuses.json的路径
    let path = NSBundle.mainBundle().pathForResource("status", ofType: "json")!
    // 2.加载到内存中(NSData)
    let data = NSData(contentsOfFile: path)!
    // 强制try,和强制拆包一样,如果出现错误.程序立即停止运行
    let json = try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0))
        let dict = json as! [String: AnyObject]
        finished(result: dict, error: nil)
    }
    // MARK: - 发送微博
    /**
    发送微博
    
    - parameter status:   微博的内容
    - parameter finished: 回调的闭包
    */
    func sendStatus(status: String, image: UIImage?, finished: (result: [String: AnyObject]?,error: NSError?) -> ()) {
        // 1.判断access_token
        guard let access_token = HOPuserAccount.loadUserAccount()?.access_token else {
            let error = HOPNetworkError.emptyAccessToken.error()
            finished(result: nil, error: error)
            return
        }
        // 2.url
        let urlString = "2/statuses/update.json"
        // 3.请求参数
        let parameters = [
        "access_token": access_token,
            "status": status
        ]
        // 判断是否有图片
        if let img = image {
        // 别人传入了图片,发送带图片的微博
        sendImageStatus(parameters, status: status, image: img, finished: finished)
        } else {
        // 4.发送请求
        POST(urlString, parameters: parameters, success: { (_, result) -> Void in
            let dict = result as? [String: AnyObject]
            finished(result: dict, error: nil)
            }) { (_, error) -> Void in
                finished(result: nil, error: error)
        }
        }
    }
    /// 发送带图片的微博
    func sendImageStatus(parameters: [String: AnyObject], status: String,
        image: UIImage, finished: (result: [String: AnyObject]?,error: NSError?) -> ()) {
            // url
            let urlString = "https://upload.api.weibo.com/2/statuses/upload.json"
            // appendPartWithFileData
            // 使用AFN上传图片,并发送微博
POST(urlString, parameters: parameters, constructingBodyWithBlock: { (formData) -> Void in
    let imageData = UIImagePNGRepresentation(image)!
    // 上传图片
    // data: 要上传的二进制
    // name: api里面指定的pic
    // fileName: 服务器保存的文件名,如果API有指定就按API指定的填,如果没有指定,可以随便填
    // mimeType: image/png, image/jpeg, image/gif
    formData.appendPartWithFileData(imageData, name: "pic", fileName: "", mimeType: "image/png")
    
    }, success: { (_, result) -> Void in
        let dict = result as? [String: AnyObject]
        finished(result: dict, error: nil)
    }) { (_, error) -> Void in
        finished(result: nil, error: error)
        }
    
    
    }
    
    
    
    
    
}








